﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;

namespace HoldemHook
{

    public enum TileClass:uint
    {
        Unknown     = 0,
        PlayerNick  = 1,
        Bank        = 2,
        Stake       = 4,
        TotalBank   = 8,
        Button      =16,
        Money       =32 // if have "$"
    }

    public class Tile
    {
        public uint Clazz;
        public int Index;
        public float X, Y;
        public double Phi;
        public string Text;
        public Mosaic Mosaic;

        public Tile(uint clazz, float x, float y, string text)
        {
            Clazz=clazz;
            X = x;
            Y = y;
            Index = -1;
            Text = text;
        }

        public float Dist2(float xx, float yy)
        {
            return (X-xx)*(X-xx)+(Y-yy)*(Y-yy);
        }

        public bool IsNearY(float xx, float yy)
        {
            return Math.Abs((double)(yy - Y) / Mosaic.WordHeight) < 0.5;
        }

        public bool IsFarY(float xx, float yy)
        {
            return Math.Abs((double)(yy-Y)/Mosaic.WordHeight)>4;
        }

        public bool IsNearX(float xx, float yy)
        {
            return Math.Abs((double)(xx - X) / Mosaic.WordWidth) < 0.5;
        }

        public bool IsFarX(float xx, float yy)
        {
            return Math.Abs((double)(xx-X)/Mosaic.WordWidth)>4;
        }

        public bool IsNear(float xx, float yy)
        {
            return Math.Sqrt(Dist2(xx, yy)) < Mosaic.WordHeight;
        }

        public override string ToString()
        {
            return string.Format("{0}@{4}({1},{2})'{3}' PHI={5};\n", Clazz, X, Y, Text, Index,Math.Round(Phi*180/Math.PI));
        }
    }


    public class TileList : List<Tile>
    {
        public enum SearchOption
        {
            Near,
            Far
        }

        public int IndexOfExtremeDist(float x, float y, ref float dist2, SearchOption opt)
        {
            dist2 = opt==SearchOption.Near?int.MaxValue:int.MinValue;
            int found_i=-1;

            for(int i=0;i<Count;i++)
            {
                float  d = this[i].Dist2(x,y);
                if(opt==SearchOption.Near)
                {
                    if(d<dist2)
                    {
                        found_i=i;
                        dist2=d;
                    }
                }else{
                    if(d>dist2)
                    {
                        found_i=i;
                        dist2=d;
                    }
                }
            }
            return found_i;
        }
    }

    public class Mosaic
    {
        TileList list = new TileList();
        
        public static int WordHeight=12;
        public static int WordWidth=3*12;
        public int X0, Y0;

        public TileList Tiles { get { return list; } }

        public Mosaic()
        {
        }

        public void Add(float x, float y, string text, uint opts)
        {
            float dist2 = 0;
            int ndx = list.IndexOfExtremeDist(x, y, ref dist2, TileList.SearchOption.Near);
            if (ndx >= 0 && dist2 < WordHeight/2)
            {
                list[ndx].Text = text;
            }
            else
            {
                list.Add(new Tile(opts, x, y, text));
            }
        }

        public void CalcAngles(int x0, int y0)
        {
            for (int i = 0; i < list.Count; i++)
            {
                Tile tile = list[i];
                tile.Phi = Math.Atan2(tile.Y - y0, tile.X - x0);
            }
        }

        static int CompareByPhi(Tile a, Tile b)
        {
            if (a.Phi == b.Phi) return 0;
            return a.Phi-b.Phi>0?1:-1;
        }

        public void Sort()
        {
            list.Sort(CompareByPhi);
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < list.Count; i++)
            {
                sb.AppendFormat("[{0}]", list[i].ToString());
            }
            return sb.ToString();
        }
    }
}